package com.netease.nie.facade;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.netease.nie.base.cache.CacheParam;
import com.netease.nie.base.cache.DataOperation;
import com.netease.nie.base.cache.redis.RedisManager;
import com.netease.nie.base.exceptions.BusinessException;
import com.netease.nie.base.utils.CustomDateFormatUtils;
import com.netease.nie.base.utils.PageUtils;
import com.netease.nie.common.CommonBusinessTools;
import com.netease.nie.constants.BusinessConstants;
import com.netease.nie.constants.CachePrefixConstants;
import com.netease.nie.constants.CustomGoodsConstants;
import com.netease.nie.constants.DisplayTypeConstants;
import com.netease.nie.constants.GoodsTypeStants;
import com.netease.nie.dto.MyExchangeDto;
import com.netease.nie.model.ExchangeCode;
import com.netease.nie.model.ExchangeGoodsInfo;
import com.netease.nie.model.GoodsInfo;
import com.netease.nie.model.Orders;
import com.netease.nie.service.ExchangeCodeService;
import com.netease.nie.service.ExchangeGoodsInfoService;
import com.netease.nie.service.GoodsInfoService;
import com.netease.nie.service.OrderService;

/**
 * 我的兑换接口
 * @author Derek Xu
 * @CreateDate Jul 21, 2016
 */
@Service
public class MyExchangeFacadeImpl extends CommonBusinessTools implements MyExchangeFacade {

	@Autowired
	private OrderService orderService;
	
	@Autowired
	private ExchangeGoodsInfoService exchangeGoodsInfoService;
	
	@Autowired
	private GoodsInfoService GoodsInfoService;
	
	@Autowired
	private ExchangeCodeService exchangeCodeService;
	
	private final Logger logger = Logger.getLogger(MyExchangeFacadeImpl.class);
	
	private static final String EXCHANGED_LIST_PREFIX = CachePrefixConstants.GoodsPrefix.EXCHANGED_LIST_PREFIX;
	
	public List<MyExchangeDto> listMyExchangeByUserId(final Long userId, final Integer page, final Integer pageSize) {
		if (page == null || page < 0 || pageSize == null || pageSize <= 0)
			throw new BusinessException(
					BusinessConstants.PAGE_PARAM_ILLEGAL.getCode(), 
					BusinessConstants.PAGE_PARAM_ILLEGAL.getMsg());
		
		if (page >= 2) {	//如果大于第2页，直接从数据库找
			List<MyExchangeDto> myExchangeDtoList = getMyExchangeCodeDtoList(userId, page, pageSize);
			return myExchangeDtoList;
		} else { //第1页在缓存找
			DataOperation dataOperation = new DataOperation() {	//如果缓存没有，则需要去数据库取数据
				public Object operate() {
					return getMyExchangeCodeDtoList(userId, page, pageSize);
				}
			};
			String orderListKey = EXCHANGED_LIST_PREFIX + userId;
			List<String> keyList = new ArrayList<>();
			keyList.add(orderListKey);
			CacheParam cacheParam = new CacheParam();
			cacheParam.setKeyList(keyList);
			cacheParam.setPrefix(EXCHANGED_LIST_PREFIX);
			
			int start = PageUtils.getPageStartIndex(page, pageSize);
			int end = PageUtils.getPageEndIndex(page, pageSize);
			
			cacheParam.setStartIndex(start);
			cacheParam.setEndIndex(end);
			
			RedisManager redisManager = new RedisManager(cacheParam, dataOperation);
			List<MyExchangeDto> myExchangeDtoList = 
					(List<MyExchangeDto>) redisManager.passiveOperateCache(MyExchangeDto.class);
			
			if (myExchangeDtoList != null) {

				//替换商品图片
				replaceThumbnailUrlInMyExchangeDto(myExchangeDtoList, DisplayTypeConstants.WAP.getCode());
				return myExchangeDtoList;
			}
			else
				return Collections.emptyList();
		}
	}

	/**
	 * 根据商品id获取商品详细信息
	 * @param ids
	 * @return
	 */
	private List<MyExchangeDto> getMyExchangeCodeDtoList(Long userId, Integer page, Integer pageSize) {
		int pageIndex = PageUtils.getPageStartIndex(page, pageSize);
		List<Orders> ordersList = orderService.listLastThreeMonthsOrderByUserId(userId, pageIndex, pageSize);	//获取近三个月的记录
		
		int ordersListSize = ordersList.size();
		List<Integer> ids = new ArrayList<>();	//提取商品id
		List<Integer> exchangeCodeIds = new ArrayList<>(ordersListSize);
		for (int i = 0; i < ordersList.size(); ++i) {
			Orders orders = ordersList.get(i);
			
			Integer customGoodsCode = orders.getCustomGoodsCode();
			if(customGoodsCode != CustomGoodsConstants.EXCHANGE.getCode()){  //仅查询兑换商品
				ordersList.remove(i);
				i--;
				continue;				
			}			
			Integer id = orders.getCustomGoodsId();
			ids.add(id);
			
			Integer goodsType = orders.getGoodsType();
			if (goodsType == GoodsTypeStants.REDEEM_CODE.getCode()) {	//兑换类型是兑换码,提取兑换码id
				Integer exchangeCodeId = orders.getExchangeCodeId();
				exchangeCodeIds.add(exchangeCodeId);
			}
		}
		
		List<MyExchangeDto> myExchangeCodeDtoList = 
				getMyExchangeCodeDtoListFromDb(ordersList, ids, exchangeCodeIds);
		
		return myExchangeCodeDtoList;
	}
	
	/**
	 * 从数据库中取商品信息、扩展信息和兑换码信息
	 * @param orderList
	 * @param ids
	 * @param exchangeCodeIds
	 * @return
	 */
	private List<MyExchangeDto> getMyExchangeCodeDtoListFromDb(List<Orders> orderList, 
			List<Integer> ids, List<Integer> exchangeCodeIds) {

		Map<Integer, ExchangeGoodsInfo> exchangeGoodsInfoMap = new HashMap<>();
		Map<Integer, GoodsInfo> goodsInfoMap = new HashMap<>();
		Map<Integer, ExchangeCode> exchangeCodeMap = new HashMap<>();
		List<Integer> abstractIds = new ArrayList<>();
		
		if (!ids.isEmpty()) {
			exchangeGoodsInfoMap = exchangeGoodsInfoService.queryExchangeGoodsInfoByIds(ids);	//取商品信息

		}
		if (!exchangeCodeIds.isEmpty()) {
			exchangeCodeMap = exchangeCodeService.queryExchangeCodeByIds(exchangeCodeIds);	//取兑换码信息
		}
		
		Set<Entry<Integer, ExchangeGoodsInfo>> entrySet = exchangeGoodsInfoMap.entrySet();
		for (Entry<Integer, ExchangeGoodsInfo> entry : entrySet) {
			ExchangeGoodsInfo exchangeGoodsInfo = entry.getValue();
			abstractIds.add(exchangeGoodsInfo.getGoodsId());			
		}		
		goodsInfoMap = GoodsInfoService.queryGoodsInfoByIds(abstractIds);	//取抽象商品信息
		
		int orderListSize = orderList.size();
		List<MyExchangeDto> myExchangeDtoList = new ArrayList<>(orderListSize);
		MyExchangeDto myExchangeDto = null;
		ExchangeGoodsInfo exchangeGoodsInfo = null;
		GoodsInfo goodsInfo = null;
		ExchangeCode exchangeCode = null;
		for (int i = 0; i < orderListSize; ++i) {
			Orders orders = orderList.get(i);
			Long userId = orders.getUserId();
			Integer exchangeGoodsId = orders.getCustomGoodsId();
			Integer exchangeCodeId = orders.getExchangeCodeId();
			myExchangeDto = new MyExchangeDto();
			
			if (exchangeGoodsInfoMap.containsKey(exchangeGoodsId)) {	//如果商品存在
				Integer generateDate = orders.getGenerateDate();
				Long createTime = orders.getCreateTime();
				String exchangeDateStr = CustomDateFormatUtils.getyyyyMMddHHmmssStr(createTime);	//兑换时间
				myExchangeDto.setExchangeDate(exchangeDateStr);
				myExchangeDto.setOrderId(orders.getId());
				
				exchangeGoodsInfo = exchangeGoodsInfoMap.get(exchangeGoodsId);
				Integer abstractId = exchangeGoodsInfo.getGoodsId();
				myExchangeDto.setUserId(userId);
				myExchangeDto.setGoodsId(exchangeGoodsInfo.getId());
				myExchangeDto.setTitle(exchangeGoodsInfo.getTitle());
				myExchangeDto.setSubTitle(exchangeGoodsInfo.getSubTitle());
				myExchangeDto.setGoodsType(exchangeGoodsInfo.getGoodsType());
				myExchangeDto.setThumbnailWapUrl(exchangeGoodsInfo.getThumbnailWapUrl());
				myExchangeDto.setThumbnailWebUrl(exchangeGoodsInfo.getThumbnailWebUrl());
				
				if (exchangeGoodsInfo.getGoodsType() != GoodsTypeStants.ENTITY.getCode()) { //实物商品不需要有效期
					String expireDate = "";
					Integer fixedValidDate = exchangeGoodsInfo.getFixedValidDate();
					Integer changeableValidDate = exchangeGoodsInfo.getChangeableValidDate();
					if (fixedValidDate != null && fixedValidDate != 0)
						expireDate = CustomDateFormatUtils.getyyyyMMddStr(fixedValidDate);
					else if (changeableValidDate != null)
						expireDate = computeExpireTime(changeableValidDate, generateDate);
					myExchangeDto.setExpireDate(expireDate); //过期时间
				}
				
				if (goodsInfoMap.containsKey(abstractId)) {                         //电子凭证
					goodsInfo = goodsInfoMap.get(abstractId);
					if(goodsInfo.getElectronicCredentialUrl() != null)
						myExchangeDto.setElectronicCredentialUrl(goodsInfo.getElectronicCredentialUrl());
				}				
				if (exchangeCodeMap.containsKey(exchangeCodeId)) {                     //兑换码
					exchangeCode = exchangeCodeMap.get(exchangeCodeId);
					myExchangeDto.setExchangeCodeId(exchangeCodeId);
					myExchangeDto.setExchangeCode(exchangeCode.getExchangeCode());
				}
			}
			
			myExchangeDtoList.add(myExchangeDto);
		}
		
		return myExchangeDtoList;
	}
	
	/**
	 * 计算过期时间
	 * @param changeableValidDate
	 * @param generateDate
	 * @return
	 */
	private String computeExpireTime(Integer changeableValidDate, Integer generateDate) {
		DateFormat df = new SimpleDateFormat("yyyyMMdd");
		Date parsedDate = null;
		try {
			parsedDate = df.parse(CustomDateFormatUtils
					.getyyyyMMddStr(generateDate));
		} catch (ParseException e) {
			logger.error(e.getMessage());
		}
		if (parsedDate != null) {
			Date expireTime = DateUtils
					.addDays(parsedDate, changeableValidDate);
			return CustomDateFormatUtils.getyyyyMMddStr(expireTime.getTime());
		}
		return StringUtils.EMPTY;
	}
}
